import SwiftUI

// MARK: - Custom Transitions
extension AnyTransition {
    static var slideUpWithOpacity: AnyTransition {
        .asymmetric(
            insertion: .move(edge: .bottom).combined(with: .opacity),
            removal: .move(edge: .bottom).combined(with: .opacity)
        )
    }
    
    static var scaleAndSlide: AnyTransition {
        .asymmetric(
            insertion: .scale(scale: 0.8).combined(with: .move(edge: .trailing)),
            removal: .scale(scale: 1.2).combined(with: .move(edge: .leading))
        )
    }
    
    static var blurAndScale: AnyTransition {
        .asymmetric(
            insertion: .scale(scale: 0.9).combined(with: .opacity),
            removal: .scale(scale: 1.1).combined(with: .opacity)
        )
    }
}

// MARK: - Custom Button Styles
struct PressableButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 0.95 : 1.0)
            .opacity(configuration.isPressed ? 0.8 : 1.0)
            .animation(StyleConstants.Animation.quick, value: configuration.isPressed)
    }
}

struct BounceButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 1.1 : 1.0)
            .animation(StyleConstants.Animation.springBouncy, value: configuration.isPressed)
    }
}

struct FloatingButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 0.9 : 1.0)
            .shadow(
                color: .black.opacity(configuration.isPressed ? 0.1 : 0.3),
                radius: configuration.isPressed ? 2 : 8,
                x: 0,
                y: configuration.isPressed ? 1 : 4
            )
            .animation(StyleConstants.Animation.quick, value: configuration.isPressed)
    }
}

// MARK: - Animated Views
struct PulsingView: View {
    @State private var isPulsing = false
    let color: Color
    let size: CGFloat
    
    var body: some View {
        Circle()
            .fill(color.opacity(0.3))
            .frame(width: size, height: size)
            .scaleEffect(isPulsing ? 1.2 : 0.8)
            .opacity(isPulsing ? 0.0 : 1.0)
            .animation(
                Animation.easeInOut(duration: 2.0).repeatForever(autoreverses: false),
                value: isPulsing
            )
            .onAppear {
                isPulsing = true
            }
    }
}

struct BreathingView: View {
    @State private var isBreathing = false
    let content: AnyView
    
    init<Content: View>(@ViewBuilder content: () -> Content) {
        self.content = AnyView(content())
    }
    
    var body: some View {
        content
            .scaleEffect(isBreathing ? 1.05 : 1.0)
            .animation(
                Animation.easeInOut(duration: 3.0).repeatForever(autoreverses: true),
                value: isBreathing
            )
            .onAppear {
                isBreathing = true
            }
    }
}

struct ShimmerView: View {
    @State private var moveShimmer = false
    let gradient: LinearGradient
    
    init() {
        self.gradient = LinearGradient(
            gradient: Gradient(colors: [
                Color.white.opacity(0.0),
                Color.white.opacity(0.3),
                Color.white.opacity(0.0)
            ]),
            startPoint: .leading,
            endPoint: .trailing
        )
    }
    
    var body: some View {
        RoundedRectangle(cornerRadius: StyleConstants.Layout.cornerRadius)
            .fill(gradient)
            .rotationEffect(.degrees(30))
            .offset(x: moveShimmer ? 300 : -300)
            .animation(
                Animation.linear(duration: 1.5).repeatForever(autoreverses: false),
                value: moveShimmer
            )
            .onAppear {
                moveShimmer = true
            }
    }
}

// MARK: - Loading States
struct SkeletonLoadingView: View {
    @State private var isAnimating = false
    let width: CGFloat
    let height: CGFloat
    let cornerRadius: CGFloat
    
    var body: some View {
        RoundedRectangle(cornerRadius: cornerRadius)
            .fill(Color.gray.opacity(0.3))
            .frame(width: width, height: height)
            .overlay(
                ShimmerView()
                    .clipped()
            )
            .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
    }
}

// MARK: - Haptic Feedback
struct HapticFeedback {
    static func light() {
        let impactFeedback = UIImpactFeedbackGenerator(style: .light)
        impactFeedback.impactOccurred()
    }
    
    static func medium() {
        let impactFeedback = UIImpactFeedbackGenerator(style: .medium)
        impactFeedback.impactOccurred()
    }
    
    static func heavy() {
        let impactFeedback = UIImpactFeedbackGenerator(style: .heavy)
        impactFeedback.impactOccurred()
    }
    
    static func success() {
        let notificationFeedback = UINotificationFeedbackGenerator()
        notificationFeedback.notificationOccurred(.success)
    }
    
    static func error() {
        let notificationFeedback = UINotificationFeedbackGenerator()
        notificationFeedback.notificationOccurred(.error)
    }
    
    static func warning() {
        let notificationFeedback = UINotificationFeedbackGenerator()
        notificationFeedback.notificationOccurred(.warning)
    }
}

// MARK: - Animated Number Counter
struct AnimatedNumberView: View {
    let value: Int
    @State private var displayedValue: Int = 0
    
    var body: some View {
        Text("\(displayedValue)")
            .onAppear {
                animateNumber()
            }
            .onChange(of: value) { _, _ in
                animateNumber()
            }
    }
    
    private func animateNumber() {
        let steps = 20
        let stepValue = Double(value - displayedValue) / Double(steps)
        
        for i in 0...steps {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * 0.02) {
                displayedValue = displayedValue + Int(stepValue)
                if i == steps {
                    displayedValue = value
                }
            }
        }
    }
}

// MARK: - Parallax Effect
struct ParallaxView<Content: View>: View {
    let content: Content
    let magnitude: CGFloat
    
    init(magnitude: CGFloat = 20, @ViewBuilder content: () -> Content) {
        self.magnitude = magnitude
        self.content = content()
    }
    
    var body: some View {
        GeometryReader { geometry in
            content
                .offset(y: -geometry.frame(in: .global).minY * magnitude / 100)
        }
    }
}

// MARK: - View Extensions for Animation
extension View {
    func pressableStyle() -> some View {
        self.buttonStyle(PressableButtonStyle())
    }
    
    func bounceStyle() -> some View {
        self.buttonStyle(BounceButtonStyle())
    }
    
    func floatingStyle() -> some View {
        self.buttonStyle(FloatingButtonStyle())
    }
    
    func withHapticFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle = .medium) -> some View {
        self.onTapGesture {
            let impactFeedback = UIImpactFeedbackGenerator(style: style)
            impactFeedback.impactOccurred()
        }
    }
    
    func slideInFromBottom(delay: Double = 0) -> some View {
        self.transition(.slideUpWithOpacity)
            .animation(StyleConstants.Animation.smooth.delay(delay), value: true)
    }
    
    func breathingEffect() -> some View {
        BreathingView {
            self
        }
    }
}